home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
t3_1
/
nexttsrc.lha
/
nexttsources
/
nexttsystem
/
tea.el
< prev
Wrap
Lisp/Scheme
|
1993-07-23
|
15KB
|
421 lines
;;; -*-Emacs-Lisp-*- Tea under emacs stuff.
;; Copyright (C) 1985, 1986 Bill Rozas & Jonathan Rees & Richard M. Stallman
;; This file is part of GNU Emacs.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY. No author or distributor
;; accepts responsibility to anyone for the consequences of using it
;; or for whether it serves any particular purpose or works at all,
;; unless he says so in writing. Refer to the GNU Emacs General Public
;; License for full details.
;; Everyone is granted permission to copy, modify and redistribute
;; GNU Emacs, but only under the conditions described in the
;; GNU Emacs General Public License. A copy of this license is
;; supposed to have been given to you along with GNU Emacs so you
;; can know your rights and responsibilities. It should be in a
;; file named COPYING. Among other things, the copyright notice
;; and this notice must be preserved on all copies.
;; xscheme.el adapted from shell.el to scheme.
;; tea.el adapted for T from xscheme.el by J Rees.
;; Cream and sugar by Joshua Guttman and John D. Ramsdell.
;; Some suggestions for your .emacs file.
;;
;;(autoload 'run-tea "tea"
;; "Run an inferior T process."
;; t)
;;
;; (setq auto-mode-alist
;; (cons '("\\.t$" . scheme-mode) ; Scheme mode for T files.
;; auto-mode-alist))
;;
;; A suggestion for modifying the etags program so that it knows about T.
;; You should modify the few lines that allow etags to conclude that
;; files that end with ".t" are lisp source code. Here is the differences
;; for the current version of etags.
;;364c364
;;< /* .l or .el or .lisp (or .cl or .clisp or .t!) implies lisp source code */
;;---
;;> /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */
;;366d365
;;< !strcmp (cp + 1, "t") ||
(provide 'tea)
(setq scheme-mit-dialect nil)
(require 'scheme)
(require 'shell)
(defvar inferior-tea-mode-map nil)
(setq completion-ignored-extensions
(append '(".mo" ".mi" ".mn" ".so" ".si" ".sn")
completion-ignored-extensions))
(if inferior-tea-mode-map
nil
(setq inferior-tea-mode-map (copy-keymap shell-mode-map))
(define-key inferior-tea-mode-map "\C-c\C-a" 'quit-shell-subjob)
(define-key inferior-tea-mode-map "\C-c\C-g" 'interrupt-shell-subjob)
(define-key inferior-tea-mode-map "\C-d" 'delete-char-or-maybe-send-eof)
(define-key inferior-tea-mode-map "\C-x\C-e" 'tea-get-definition)
(define-key inferior-tea-mode-map "\e\C-x" 'tea-get-definition)
(define-key inferior-tea-mode-map "\e\C-l" 'tea-load-file)
(define-key inferior-tea-mode-map "\e\C-c" 'tea-compile-file)
(define-key inferior-tea-mode-map "\C-c\C-y" 'yank-input)
(define-key inferior-tea-mode-map "\ey" 'yank-pop-input-or-kill)
(define-key inferior-tea-mode-map "\C-m" 'tea-send-input)
(define-key inferior-tea-mode-map "\C-cl" 'tea-load-file)
(define-key inferior-tea-mode-map "\C-cc" 'tea-compile-file)
(define-key inferior-tea-mode-map "\C-co" 'tea-object-unhash)
(define-key inferior-tea-mode-map "\t" 'scheme-indent-line)
(define-key inferior-tea-mode-map "\177" 'backward-delete-char-untabify)
(define-key inferior-tea-mode-map "\e\C-q" 'scheme-indent-sexp)
(define-key inferior-tea-mode-map "\e\C-s" 'find-scheme-definition)
(define-key inferior-tea-mode-map "\e " 'fixup-whitespace))
(define-key scheme-mode-map "\C-ce" 'tea-send-definition)
(define-key scheme-mode-map "\C-c\C-e" 'tea-send-definition-and-go)
(define-key scheme-mode-map "\C-cc" 'tea-compile-definition)
(define-key scheme-mode-map "\C-c\C-c" 'tea-compile-definition-and-go)
(define-key scheme-mode-map "\C-c\C-g" 'tea-reset-process)
(define-key scheme-mode-map "\C-cz" 'switch-to-tea)
(define-key scheme-mode-map "\C-cd" 'tea-define-operation)
(define-key scheme-mode-map "\e\^Q" 'scheme-indent-sexp)
(define-key scheme-mode-map "\eg" 'balance-defuns)
(define-key scheme-mode-map "\eq" 'fill-commented-paragraph)
(define-key scheme-mode-map "\e\C-i" 'indent-relative)
(define-key scheme-mode-map "\e\C-m" 'auto-fill-mode)
(define-key scheme-mode-map "\C-x\C-s" 'balance-defuns-and-save)
(define-key scheme-mode-map "\e\C-c" 'tea-eval-expression)
(define-key scheme-mode-map "\e " 'fixup-whitespace)
(defun inferior-tea-mode ()
"Major mode for interacting with an inferior T process.
The following commands are available:
\\{inferior-tea-mode-map}
Entry to this mode calls the value of tea-mode-hook with no arguments,
if that value is non-nil. Likewise with the value of shell-mode-hook.
tea-mode-hook is called after shell-mode-hook.
You can send text to the inferior Tea from other buffers
using the commands send-region, send-string and \\[tea-send-definition].
Commands:
Delete converts tabs to spaces as it moves back.
Tab indents for Scheme; with argument, shifts rest
of expression rigidly with the current line.
Meta-Control-Q does Tab on each line starting within following expression.
Paragraphs are separated only by blank lines. Semicolons start comments.
Return at end of buffer sends line as input.
Return not at end copies rest of line to end and sends it.
C-d at end of buffer sends end-of-file as input.
C-d not at end or with arg deletes or kills characters.
C-c C-c interrupts the shell or its current subjob if any.
C-z stops, likewise. C-\\ sends quit signal, likewise.
There's other stuff too which isn't yet documented."
(interactive)
(kill-all-local-variables)
(setq major-mode 'inferior-tea-mode)
(setq mode-name "Tea under Emacs")
(setq mode-line-process '(": %s"))
(scheme-mode-variables)
(use-local-map inferior-tea-mode-map)
(make-local-variable 'last-input-start)
(setq last-input-start (make-marker))
(make-local-variable 'last-input-end)
(setq last-input-end (make-marker))
(run-hooks 'shell-mode-hook 'scheme-mode-hook))
(defun args-to-list (string)
(let ((where (string-match "[ \t]" string)))
(cond ((null where) (list string))
((not (= where 0))
(cons (substring string 0 where)
(args-to-list (substring string (+ 1 where)
(length string)))))
(t (let ((pos (string-match "[^ \t]" string)))
(if (null pos)
nil
(args-to-list (substring string pos (length string)))))))))
(defvar tea-program-name "t"
"Program invoked by the tea and run-tea commands")
(defvar tea-process nil
"Process currently running tea under emacs.")
(defun tea (arg)
"Run an inferior Tea process reading a command line from the terminal."
(interactive "sExtra arguments to tea: ")
(pop-to-buffer
(apply 'make-shell (append (list "tea" tea-program-name nil)
(args-to-list arg)
'("-emacs"))))
(setq tea-process (get-buffer-process "*tea*"))
(inferior-tea-mode))
(defun run-tea (arg)
"Run an inferior Tea process.
Input and output via buffer *tea*.
With argument it asks for a command line. "
(interactive "P")
(if arg
(call-interactively 'tea)
(pop-to-buffer (make-shell "tea" tea-program-name nil "-h" "8000000"))
(inferior-tea-mode)
(setq tea-process (get-buffer-process "*tea*"))
(message "")))
(defvar big-tea-size "24000008"
"*Size (in string form) for each heap in a big invocation of Tea.")
(defun big-tea ()
"Run an inferior Tea process with two big heaps.
The meaning of \"big\" is controlled by the variable BIG-TEA-SIZE (q.v.).
Input and output via buffer *tea*. "
(interactive)
(tea (format "-h %s" big-tea-size)))
(defun balance-defuns (buff)
"Check that every defun in BUFF is balanced (current-buffer if interactive)."
(interactive (list (current-buffer)))
(set-buffer buff)
(let ((next-end (point-min)))
(condition-case ddd
(progn
(while (setq next-end (scan-sexps next-end 1)))
(if (interactive-p)
(message "All defuns balanced.")
t))
(error
(push-mark)
(goto-char next-end)
(cond ((interactive-p)
(ding)
(message "Unbalanced defun."))
(t nil))))))
(defun balance-defuns-and-save (force)
"Call balanced-defuns on current-buffer and save it if all defuns are balanced.
Prefix arg means force save without checking for balance."
(interactive "P")
(if (or force (balance-defuns (current-buffer)))
(save-buffer)
(ding)
(message "Unbalanced defun -- buffer not saved.")))
(defun tea-send-definition ()
"Send the current definition to the Tea process made by M-x run-tea."
(interactive)
(save-excursion
(end-of-defun)
(let ((end (point)))
(beginning-of-defun)
(send-region tea-process (point) end)
(send-string tea-process "\n"))))
(defun switch-to-tea ()
"Switch to the *tea* buffer."
(interactive)
(pop-to-buffer "*tea*"))
(defun tea-eval-expression (str)
"Read a string from the minibuffer and send it to inferior tea process."
(interactive "sTea Eval: ")
(send-string tea-process (concat str " repl-wont-print\n")))
(defun tea-funcall (fn-str arg-str)
"Read a FN-STR and ARG-STR from the minibuffer and send (FN-STR ARG-STR) to
inferior tea process."
(interactive "sTea Function: \nsArguments: ")
(tea-eval-expression
(format "(%s %s)" fn-str arg-str)))
(defun tea-send-definition-and-go ()
"Send the current definition to the inferior Tea, and switch to *tea* buffer."
(interactive)
(tea-send-definition)
(switch-to-tea))
(defun tea-compile-definition ()
"Compile the current definition to the T process made by M-x run-tea."
(interactive)
(save-excursion
(end-of-defun)
(let ((end (point)))
(beginning-of-defun)
(send-string tea-process "(orbit '")
(send-region tea-process (point) end)
(send-string tea-process ")\n"))))
(defun tea-compile-definition-and-go ()
"Send and compile the current definition to the inferior T, and switch to *tea* buffer."
(interactive)
(tea-compile-definition)
(switch-to-tea))
(defun delete-char-or-maybe-send-eof (arg)
"Delete ARG characters forward, or send an EOF to T if at end of buffer."
(interactive "p")
(if (eobp)
(send-string tea-process "#.eof\n")
(delete-char arg)))
(defvar input-ring '()
"List of put-in text sequences.")
(defvar input-ring-yank-pointer '()
"The tail of the input ring whose car is the last thing yanked.")
;;; Newline
(defun tea-send-input ()
"Send input to inferior T process."
(interactive nil)
(shell-send-input)
(save-excursion
(goto-char last-input-end)
(if (bolp) (backward-char))
(copy-region-as-input last-input-start (point))))
(defun copy-region-as-input (beg end)
"Save the region as if put in, but don't put it in."
(interactive "r")
(setq input-ring (cons (buffer-substring beg end) input-ring))
(if (> (length input-ring) kill-ring-max)
(setcdr (nthcdr (1- kill-ring-max) input-ring) nil))
(setq input-ring-yank-pointer input-ring))
(defun rotate-input-pointer (arg)
"Rotate the yanking point in input ring."
(interactive "p")
(let ((length (length input-ring)))
(if (zerop length)
(error "Input ring is empty")
(setq input-ring-yank-pointer
(nthcdr (% (+ arg (- length (length input-ring-yank-pointer)))
length)
input-ring)))))
;;; Meta-Y
(defun yank-pop-input-or-kill (arg)
"Replace just-yanked stretch of killed-text with a different stretch.
This command is allowed only immediately after a yank , yank-input ,
or itself.
At such a time, the region contains a stretch of reinserted
previously-killed text. yank-pop deletes that text and inserts in its
place a different stretch of killed text.
With no argument, the previous kill is inserted.
With argument n, the n'th previous kill is inserted.
If n is negative, this is a more recent kill.
The sequence of kills wraps around, so that after the oldest one
comes the newest one."
(interactive "*p")
(if (eq last-command 'yank)
(yank-pop arg)
(if (not (eq last-command 'yank-input))
(error ;"Previous command was not a yank"
(symbol-name last-command))
(progn
(setq this-command 'yank-input)
(let ((before (< (point) (mark))))
(delete-region (point) (mark))
(rotate-input-pointer arg)
(set-mark (point))
(insert (car input-ring-yank-pointer))
(if before (exchange-point-and-mark)))))))
;;; Control-Meta-Y
(defun yank-input (&optional arg)
"Reinsert the last input.
With just C-U as argument, same but put point in front (and mark at end).
With argument n, reinsert the nth most recent input.
See also the command \\[yank-pop-input-or-kill]."
(interactive "*P")
(rotate-input-pointer (if (listp arg) 0
(if (eq arg '-) -1
(1- arg))))
(push-mark (point))
(insert (car input-ring-yank-pointer))
(if (consp arg)
(exchange-point-and-mark)))
(defun tea-object-unhash()
"Insert (object-unhash ) and poise cursor before left-paren."
(interactive)
(insert-string "(object-unhash )")
(backward-char 1))
(defun tea-load-file (file-name)
"Load a Tea file into the inferior Tea process."
(interactive
(list
(expand-file-name
(read-file-name "Load Tea file: " default-directory "" t))))
(send-string tea-process (concat "(load \""
file-name
"\"\)\n"))
(switch-to-tea))
(defun tea-compile-file (file-name)
"Compile a Tea file in the inferior Tea process."
(interactive "fCompile Tea file: ")
(send-string tea-process (concat "(compile-file \""
file-name
"\"\)\n"))
(switch-to-tea))
(defun tea-chdir (dir)
"Switch tea process to new current-directory."
(interactive "DChange to directory: ")
(send-string tea-process (concat "((*value t-implementation-env 'unix-chdir) \""
(substring (expand-file-name dir) 0 -1)
"\"\)\n"))
(switch-to-tea)
(setq default-directory dir))
(defun tea-grep (target)
"run grep asynchronously, ignoring case, searching for TARGET throughout the files *.t"
(interactive "sTarget: ")
(grep (format "-i %s *.t" target)))
(put 'labels 'scheme-indent-hook 1)
(put 'xcase 'scheme-indent-hook 1)
(put 'select 'scheme-indent-hook 1)
(put 'xselect 'scheme-indent-hook 1)
(put 'typecase 'scheme-indent-hook 1)
(put 'destructure 'scheme-indent-hook 1)
(put 'destructure* 'scheme-indent-hook 1)
(put 'with-open-ports 'scheme-indent-hook 1)
(put 'bind 'scheme-indent-hook 1)
(put 'bind* 'scheme-indent-hook 1)
(put 'iterate 'scheme-indent-hook 2)
(put 'receive 'scheme-indent-hook 1)
(put 'block 'scheme-indent-hook 0)
(put 'catch 'scheme-indent-hook 1)
(put 'object 'scheme-indent-hook 1)
(put 'operation 'scheme-indent-hook 1)
(put 'join 'scheme-indent-hook 0)
(modify-syntax-entry ?[ "(]" scheme-mode-syntax-table)
(modify-syntax-entry ?] ")[" scheme-mode-syntax-table)
(modify-syntax-entry ?{ "(}" scheme-mode-syntax-table)
(modify-syntax-entry ?} "){" scheme-mode-syntax-table)